<script setup lang="ts">
import _ from 'lodash'
import { h, resolveComponent, getCurrentInstance, computed, onMounted } from 'vue'
import Emitter from '../../tools/emitter'
import AsyncValidator from 'async-validator'
import formItem from './form-item.vue'
// 导入cg-input组件
import cgInput from '../cg-input/main.vue'

// 定义组件名称
defineOptions({
  name: 'cg-form',
  componentName: 'cg-form'
})

// <{
//   values: Record<string, any>;
//   fieldCol: {
//     span: number;
//     component: string;
//   };
//   fields: Array<{
//     id: string;
//     label: string;
//     component?: string | any;
//     rules?: any;
//     trigger?: string;
//     normalize?: (value: any) => any;
//     props?: Record<string, any>;
//     on?: Record<string, Function>;
//   }>;
//   change?: (id: string, value: any) => void;
//   labelWidth: number;
//   root?: string;
// }>

interface field {
  id: string
  label: string
  component?: string | any
  rules?: any
  trigger?: string
  normalize?: (value: any) => any
  props?: Record<string, any>
  on?: Record<string, Function>
}

interface Props {
  values: Record<string, any>
  fieldCol: {
    span: number
    component: string
  }
  fields: Array<field>
  change?: (id: string, value: any) => void
  labelWidth: number
  root?: string
}

// 定义props

// 定义props
const props = withDefaults(defineProps<Props>(), {
  values: () => ({}),
  fieldCol: () => ({
    span: 12,
    component: 'span'
  }),
  labelWidth: 120
})

// 定义emits
const emit = defineEmits(['value-change'])

// 获取当前组件实例
const instance = getCurrentInstance()

// 手动实现Emitter mixin的findParent功能
function findParent(componentName: string) {
  if (!instance) return null

  let current = instance.parent
  while (current) {
    // 确保current.type有name属性
    if (current.type && typeof current.type === 'object' && 'name' in current.type) {
      if (current.type.name === componentName) {
        return current
      }
    }
    current = current.parent
  }
  return null
}

// 计算属性
const rootNode = computed(() => {
  if (props.root) {
    return findParent(props.root)
  }
  return null
})

// 表单验证方法
function validate() {
  let descriptor: Record<string, any> = {}
  if (Array.isArray(props.fields)) {
    props.fields.forEach((field) => {
      if (field.rules) {
        descriptor[field.id] = field.rules
      }
    })
    const validator = new AsyncValidator(descriptor)
    // validator.validate(props.values, (errors: any, data: any) => {
    //   console.log(errors, data)
    //   // 可以添加错误处理逻辑
    // })
  }
  return true
}

// 构建表单项方法
function buildFormItem(field: {
  id: string
  label: string
  component?: string | any
  trigger?: string
  normalize?: (value: any) => any
  props?: Record<string, any>
  on?: Record<string, Function>
}) {
  if (typeof field === 'object' && field.id) {
    let normalize = (value: any) => value
    let component = cgInput

    if (field.component) {
      if (typeof field.component === 'string') {
        component = resolveComponent(field.component)
      } else {
        component = field.component
      }
    }

    let trigger = 'onUpdate:modelValue'
    if (field.trigger) {
      trigger = _.camelCase('on-' + field.trigger)
    }

    if (field.normalize) {
      normalize = field.normalize
    }

    let itemProps: Record<string, any> = {
      modelValue: _.get(props.values, field.id),
      [trigger]: (e: any) => {
        emit('value-change', field.id, normalize(e))
      },
      ...(field.props ? field.props : {})
    }

    if (typeof field.on === 'object') {
      const eventNames = Object.keys(field.on)
      for (const eventName of eventNames) {
        itemProps[_.camelCase('on-' + eventName)] = field.on[eventName]
      }
    }

    let slot = h(component, itemProps)
    return h(formItem, { label: field.label }, { default: () => slot })
  }
  return null
}

// 渲染函数
function render() {
  console.log('fields', props.fields)
  return h('div', { class: 'cg-form' }, props.fields?.map(buildFormItem) || [])
}

// 生命周期钩子
onMounted(() => {
  // 挂载时的逻辑
})

// 暴露公共方法
defineExpose({
  validate
})
</script>

<style lang="scss">
@use './style.scss';
</style>
